﻿namespace Arms.Domain
{
    using Arms.Domain.Specifications;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;

    /// <summary>
    /// Base contract for repositories
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IRepository<T> where T : Entity
    {
        /// <summary>
        /// Queryable collection of the current set.
        /// </summary>
        /// <returns></returns>
        IQueryable<T> Query();
        /// <summary>
        /// Gets a collection of entities matching criteria that are in active state.
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        IEnumerable<T> Get(Expression<Func<T, bool>> filter = null);
        /// <summary>
        /// Gets a collection of entities matching criteria.
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        IEnumerable<T> GetAll(Expression<Func<T, bool>> filter = null);
        /// <summary>
        /// Gets a collection of entities matching specification.
        /// </summary>
        /// <param name="specification"></param>
        /// <returns></returns>
        IEnumerable<T> GetBySpecification(ISpecification<T> specification);
        /// <summary>
        /// Finds an entity by its identity.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        T Find(int id);
        /// <summary>
        /// Finds an entity that matches criteria.
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        T Single(Func<T, bool> filter);
        /// <summary>
        /// Finds the first entity that matches criteria.
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        T First(Func<T, bool> filter = null);
        /// <summary>
        /// Finds the last entity that matches criteria.
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        T Last(Func<T, bool> filter = null);
        /// <summary>
        /// Determines whether there are any entities matching the criteria.
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        bool Any(Func<T, bool> filter = null);
        /// <summary>
        /// Adds an entity.
        /// </summary>
        /// <param name="entity"></param>
        void Insert(T entity);
        /// <summary>
        /// Updates and tracks entity.
        /// </summary>
        /// <param name="entity"></param>
        void Update(T entity);
        /// <summary>
        /// Changes the state of the entity.
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="state"></param>
        void SetState(T entity, EntityActiveState state);
    }
}
